package thread.test1BaseThread;

import org.junit.Test;
import thread.test1BaseThread.domain.*;

import java.io.IOException;
import java.util.Scanner;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicStampedReference;

public class ThreadTest {


	/**
	 *
	 * 测试
	 * t1 join 然后t2线程中 调用 t1.interupt 中断t1, t1的join抛出中断异常
     * 当我们在线程上调用*join（）*方法时，调用线程进入等待状态。它一直处于等待状态，直到引用的线程终止
	 */
	@Test
	public void test1() {
		Thread t1=new Thread(new MyThread1());
		//注意这个中断，中断的是调用join的线程，而不是中断t1(下面构造方法参数传t1)
		Thread t2=new Thread(new MyThread2(Thread.currentThread()));
		t1.start();
		t2.start();
		try {
			t1.join();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("main is over");







	}
	/**
	 *
	 * sleep 和yield 不会释放锁。。
	 * join 底层调用的是wait方法,会让线程进入阻塞状态，并且会释放线程占有的锁，并交出CPU执行权限
	 * sleep,yield,join都必须捕获interupter中断异常
	 *
	 * 调用yield方法会让当前线程交出CPU权限，让CPU去执行其他的线程。
	 * 它跟sleep方法类似，同样不会释放锁。但是yield不能控制具体的交出CPU的时间，
	 * 另外，yield方法只能让拥有相同优先级的线程有获取CPU执行时间的机会。

	 注意，调用yield方法并不会让线程进入阻塞状态，而是让线程重回就绪状态，
	 它只需要等待重新获取CPU执行时间，这一点是和sleep方法不一样的
     */
	@Test
	public void test2() throws InterruptedException {
		Thread thread2=new Thread(new MyThread1());
		thread2.start();
	}

	/**
	 *
	 * interupt 方法 能中断处于阻塞状态的线程相当于给中断标志设置为true,
	 * 不能中断正在运行的线程，但是  配合 isInterrupted()方法能中断正在运行的
	 * 线程（但是一般不这样做，一般是加一个变量 isStop 来判断） see test4 ,test5
     */
	@Test
	public void test3() throws InterruptedException {
		Thread t1=new Thread(new MyThread3());
		t1.start();
		Thread.sleep(3000);
		System.out.printf("begin to interupt");
		t1.interrupt();
		System.out.println(" main is over");
	}


	/**
	 * isInterrupted()方法 中断正在运行的线程，（一般不这样做，一般是设置一个变量比如 stop来中断）
	 */
	@Test
	public void test4(){
		Thread t1=new Thread(new MyThread4());
		t1.start();
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		t1.interrupt();

		System.out.println("main is over");
	}

	/**
	 *
	 *通过设置 stop 变量来中止正在运行的线程
	 */
	@Test
	public void test5(){
		MyThread5 a=new MyThread5();
		Thread t1=new Thread(a);
		t1.start();
		try {
			Thread.sleep(1000);
			a.setStop(true);
			Thread.sleep(2000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("main is over");
	}

    /**
     * 原子操作类 AtomicInteger 这种会造成ABA问题，可以通过test8的 AtomicStampedReference来解决
     */
    @Test
    public void test7(){
        //不传参数的话默认是0
        AtomicInteger a=new AtomicInteger();
        //取值
        System.out.println(a.get());
        //设置值
        a.set(3);
        System.out.println(a.get());
        //param1,旧的值，param2,新的值，param1是期望值，如果a的值和期望
        //值相等 param2会设置成功，否则会设置失败
        a.compareAndSet(1,5);
        System.out.println(a.get());
    }

    /**
     * AtomicStampedReference
     * https://www.cnblogs.com/java20130722/p/3206742.html
     */
    @Test
    public void test8(){
        //初始stamp设置为0
        AtomicStampedReference a=new AtomicStampedReference(100,0);
    }









	/**
	 * ################################  创建进程  ####################################
	 */


	/**
	 * 第一种方式是通过 processBuilder
	 */
	@Test
	public void test100() throws IOException {
		ProcessBuilder pb = new ProcessBuilder("cmd","/c","ipconfig/all");
		Process process = pb.start();
		Scanner scanner = new Scanner(process.getInputStream(),"gbk");

		while(scanner.hasNextLine()){
			System.out.println(scanner.nextLine());
		}
		scanner.close();

	}

	@Test
	public void test101() throws IOException {
		String cmd = "cmd "+"/c "+"ipconfig/all";
		Process process = Runtime.getRuntime().exec(cmd);
		Scanner scanner = new Scanner(process.getInputStream(),"gbk");

		while(scanner.hasNextLine()){
			System.out.println(scanner.nextLine());
		}
		scanner.close();
	}
}
